package com.sunyard.manage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sunyard.constant.StatusConstant;
import com.sunyard.dal.bo.PaginationBO;
import com.sunyard.dal.bo.role.RoleAddBO;
import com.sunyard.dal.bo.role.RoleDeleteBO;
import com.sunyard.dal.bo.role.RolePopedomConfigBO;
import com.sunyard.dal.bo.role.RoleQueryBO;
import com.sunyard.dal.bo.role.RoleUpdateBO;
import com.sunyard.dal.dto.RoleDTO;
import com.sunyard.dal.entity.Operator;
import com.sunyard.dal.entity.Role;
import com.sunyard.dal.entity.RoleCopy;
import com.sunyard.dal.entity.RolePopedom;
import com.sunyard.dal.mapper.*;
import com.sunyard.manage.service.OperatorLogService;
import com.sunyard.manage.service.RoleService;
import com.sunyard.redisUtil.RedisUtil;
import com.sunyard.redisUtil.RedisUtils;
import com.sunyard.utils.DtoUtils;
import com.sunyard.utils.PrimaryKeyUtil;
import com.sunyard.utils.Response.BaseResult;
import com.sunyard.utils.Response.GetResult;
import com.sunyard.utils.TokenUtil;
import com.sunyard.utils.manage.DataGrid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author jiy.fang
 * @ClassName RoleServiceImpl
 * @Description description
 * @date 2019/7/24 19:29
 */
@Service
@Slf4j
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private RoleCopyMapper roleCopyMapper;

    @Autowired
    private OperatorMapper operatorMapper;

    @Autowired
    private OrganizationMapper organizationMapper;

    @Autowired
    private PopedomMapper popedomMapper;

    @Autowired
    TaskScenarioMapper taskScenarioMapper;

    @Autowired
    private OperatorLogService operatorLogService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private TerminalMapper terminalMapper;

    @Value("${admin.name}")
    private String admin;

    @Value("${auditor.name}")
    private String auditor;

    @Value("${operator.role.id}")
    private String operatorRole;

    @Override
    public BaseResult<DataGrid<RoleDTO>> queryRoleByPage(HttpServletRequest request, PaginationBO<RoleQueryBO> queryBO) throws Exception {
        RoleQueryBO roleQueryBO = queryBO.getParams();
        log.info("角色信息查询入参：{}", JSON.toJSONString(roleQueryBO));
        String orgId = TokenUtil.getOrgId(request.getHeader("token"));
        if (null == roleQueryBO.getOrgId() || "".equals(roleQueryBO.getOrgId())) {
            roleQueryBO.setOrgId(orgId);
        }
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("roleName", roleQueryBO.getRoleName());
        queryMap.put("operatorRole", operatorRole);
        //设置分页信息
        PageHelper.startPage(queryBO.getPageNo(), queryBO.getPageSize());
        //执行查询
        List<RoleDTO> list = roleMapper.getRoleListByPage(queryMap);
        //取分页信息
        PageInfo<RoleDTO> pageInfo = new PageInfo<>(list);
        //设置返回结果
        DataGrid<RoleDTO> dataGrid = new DataGrid<>();
        long total = pageInfo.getTotal();
        dataGrid.setTotal((int) total);
        dataGrid.setRows(list);
        return GetResult.getResult(dataGrid);
    }

    /**
     * @Description: 添加角色
     * @Author: jiy.fang
     * @Date: 2019/7/24 20:09
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult insertRole(HttpServletRequest request, RoleAddBO roleAddBO) throws Exception {
        String opId = TokenUtil.getOpId(request.getHeader("token"));
        String opName = TokenUtil.getOpName(request.getHeader("token"));
        String orgId = TokenUtil.getOrgId(request.getHeader("token"));
        //定义日志信息
        String logName = "添加角色";
        String operationDesc = "操作人" + opName + "添加了角色：" + roleAddBO.getRoleName();

        //判断角色名是否已经存在
        int existOpName = roleMapper.existRoleName(roleAddBO.getRoleName());
        if (existOpName > 0) {
            //详细日志添加
            return GetResult.getResultFail("角色名已存在");
        }
        //判断角色名是否在临时表中已经存在
        int existOpName1 = roleCopyMapper.existRoleName(roleAddBO.getRoleName());
        if (existOpName1 > 0) {
            //详细日志添加
            return GetResult.getResultFail("角色名已存在审核中");
        }
        //添加角色到角色临时表
        RoleCopy roleCopy = new RoleCopy();
        DtoUtils.cloneBeanToBean(roleCopy, roleAddBO);
        roleCopy.setRoleId(roleAddBO.getRoleId());
        roleCopy.setAuditId(roleAddBO.getAuditId());
        roleCopy.setAuditType(StatusConstant.AUDIT_TYPE_ADD);
        roleCopy.setCreateOp(opId);
        roleCopy.setAuditSn(1);
        roleCopy.setAuditOp(roleAddBO.getAuditor());
        roleCopy.setRoleState("0");
        roleCopy.setColor(roleAddBO.getColor());
        if ("1".equals(roleAddBO.getAuditType())) {
            roleCopy.setAuditFlag(StatusConstant.AUDIT_FLAG_PASS);
            //修改角色主表信息
            Role role = new Role();
            Date date = new Date();
            SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
            formatter.format(date);
            role.setCreateTime(date.toString());
            DtoUtils.cloneBeanToBean(role, roleCopy);
            if (StatusConstant.AUDIT_TYPE_ADD.equals(roleCopy.getAuditType())) {
                int resultCopy = roleCopyMapper.insert(roleCopy);
                int result = roleMapper.insert(role);
                if (result > 0 && resultCopy > 0) {
                    //将审核成功的角色在权限临时表的权限 加到 正式表
                    addRolePopedom(role, roleCopy);
                    //详细日志添加
                    operatorLogService.insert(operationDesc, logName, "1", opId, opName, orgId);
                    return GetResult.getResultSuccess("角色添加成功！");
                }
                return GetResult.getResultErr("角色添加失败！");
            }
        }
        roleCopy.setAuditFlag(StatusConstant.AUDIT_FLAG_DEFAULT);
        //返回处理结果
        int result = roleCopyMapper.insert(roleCopy);
        if (result > 0) {
            log.info("添加角色信息：添加成功，待审核。审核编号：{}", roleCopy.getAuditId());
            //详细日志添加
            operatorLogService.insert(operationDesc, logName, "1", opId, opName, orgId);
            return GetResult.getResultSuccess("添加成功，待审核！");
        }
        log.info("添加角色信息：添加失败");
        return GetResult.getResultFail("角色绑定的机构处于删除审核状态，无法操作");
    }

    @Override
    public BaseResult<GetResult> updateRole(HttpServletRequest request, RoleUpdateBO updateBO) throws Exception {
        String orgId = TokenUtil.getOrgId(request.getHeader("token"));
        String opName = TokenUtil.getOpName(request.getHeader("token"));
        //定义日志信息
        String logName = "修改角色";
        String operationDesc = "操作人" + opName + "修改了角色" + updateBO.getRoleName();

        //判断是否能够修改角色
        Role role = roleMapper.getRoleByRoleId(updateBO.getRoleId());
        String opId = TokenUtil.getOpId(request.getHeader("token"));
        if (role == null) {
            return GetResult.getResultFail("该角色不存在，请确认");
        }

        int roleCopyExist = roleCopyMapper.countRoleCopyByRoleId(updateBO.getRoleId());
        if (roleCopyExist > 0) {
            return GetResult.getResultFail("该角色存在审核记录，无法进行其他操作");
        }

        Integer taskRoleId = taskScenarioMapper.selectCountBYRoleId(updateBO.getRoleId());
        if (taskRoleId > 0) {
            return GetResult.getResultFail("该角色已经绑定任务场景，无法修改");
        }

        //员工单锁，判断该角色是否有员工绑定锁具
        int nun = terminalMapper.countOperatorByRole(role.getRoleId());
        if (nun > 0) {
            return GetResult.getResultFail("该角色存在员工单锁，无法修改");
        }

        //将修改角色信息加到临时表
        RoleCopy roleCopy = new RoleCopy();
        DtoUtils.cloneBeanToBean(roleCopy, role);
        roleCopy.setRoleName(updateBO.getRoleName());
        roleCopy.setRoleRemark(updateBO.getRoleRemark());
        roleCopy.setAuditId(PrimaryKeyUtil.getPrimaryKey());
        roleCopy.setAuditType(StatusConstant.AUDIT_TYPE_UPDATE);
        roleCopy.setCreateOp(opId);
        roleCopy.setAuditSn(roleCopyMapper.maxAuditSn(role.getRoleId()) + 1);
        roleCopy.setAuditor(updateBO.getAuditor());
        roleCopy.setEntityRecord(JSON.toJSONString(role));
        roleCopy.setColor(updateBO.getColor());
        //同步审核直接通过
        if ("1".equals(updateBO.getAuditType())) {
            roleCopy.setAuditFlag(StatusConstant.AUDIT_FLAG_PASS);
            //修改角色主表信息
            Role updateRole = new Role();
            Date date = new Date();
            SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
            formatter.format(date);
            role.setUpdateTime(date.toString());
            DtoUtils.cloneBeanToBean(updateRole, roleCopy);
            //修改角色权限
            RolePopedomConfigBO rolePopedomConfigBO = new RolePopedomConfigBO();
            rolePopedomConfigBO.setPopedomList(updateBO.getPopedomList());
            rolePopedomConfigBO.setRoleId(updateBO.getRoleId());
            rolePopedomConfigBO.setAuditor(updateBO.getAuditor());
            //配置权限
            configRolePopedom(updateBO.getAuditType(), rolePopedomConfigBO, roleCopy.getAuditId());
            roleCopyMapper.insert(roleCopy);
            int result = roleMapper.updateRole(updateRole);
            if (result > 0) {
                //详细日志添加
                operatorLogService.insert(operationDesc, logName, "1", opId, opName, orgId);
                return GetResult.getResultSuccess("角色修改成功！");
            }
            return GetResult.getResultErr("角色修改失败！");
        }
        roleCopy.setAuditFlag(StatusConstant.AUDIT_FLAG_DEFAULT);
        //修改角色权限
        RolePopedomConfigBO rolePopedomConfigBO = new RolePopedomConfigBO();
        rolePopedomConfigBO.setPopedomList(updateBO.getPopedomList());
        rolePopedomConfigBO.setRoleId(updateBO.getRoleId());
        rolePopedomConfigBO.setAuditor(updateBO.getAuditor());
        //配置权限
        configRolePopedom(updateBO.getAuditType(), rolePopedomConfigBO, roleCopy.getAuditId());
        int result = roleCopyMapper.insert(roleCopy);
        //返回处理结果
        if (result > 0) {
            log.info("修改角色信息：修改成功，待审核。审核编号: {}", roleCopy.getAuditId());
            //详细日志添加
            operatorLogService.insert(operationDesc, logName, "1", opId, opName, orgId);
            return GetResult.getResultSuccess("修改成功，待审核！");
        }
        log.info("修改角色信息：修改失败");
        return GetResult.getResultFail("修改失败");
    }

    @Override
    public void configRolePopedom(String auditType, RolePopedomConfigBO configBO, String auditId) {
        //前端传过来的权限
        List<String> popedoms = configBO.getPopedomList();
        //将重新分配的权限添加到角色权限临时表
        List<RolePopedom> rolePopedomList = new ArrayList<>();
        //查询审核序号
        int maxAuditSn = roleCopyMapper.maxAuditSn(configBO.getRoleId());
        //当前审核序号
        int nextAuditSn = maxAuditSn + 1;
        popedoms.forEach(popedomId -> {
            RolePopedom rolePopedom = new RolePopedom();
            rolePopedom.setRoleId(configBO.getRoleId());
            rolePopedom.setPopedomId(popedomId);
            rolePopedom.setAuditSn(nextAuditSn);
            rolePopedom.setAuditId(auditId);
            rolePopedomList.add(rolePopedom);
        });

        //如果是同步审核 修改角色权限直接通过
        if ("1".equals(auditType)) {
            if (rolePopedomList.isEmpty()) {
                //删除机构权限表原有的权限
                popedomMapper.deleteRolePopedom(configBO.getRoleId());
            } else {
                //删除机构权限表原有的权限
                popedomMapper.deleteRolePopedom(configBO.getRoleId());
                //新增权限
                popedomMapper.insertRolePopedom(rolePopedomList);
            }
        } else {
            if (!rolePopedomList.isEmpty()) {
                popedomMapper.insertRolePopedomTep(rolePopedomList);
            }
        }
    }

    @Override
    public List<Role> getOpenLockRoles(String popedomId,HttpServletRequest request) {
        String adminRoleId = operatorMapper.getAdminRoleId();
        if(StrUtil.isBlank(adminRoleId)){
            adminRoleId="";
        }
        List<Role> roles = roleMapper.getRoleByPopedomId(popedomId, adminRoleId);
        return roles;
    }

    @Override
    public BaseResult deleteRole(HttpServletRequest request, RoleDeleteBO roleDeleteBO) throws Exception {
        String opId = TokenUtil.getOpId(request.getHeader("token"));
        String orgId = TokenUtil.getOrgId(request.getHeader("token"));
        String opName = TokenUtil.getOpName(request.getHeader("token"));
        Role role = roleMapper.getRoleByRoleId(roleDeleteBO.getRoleId());
        if (role == null) {
            return GetResult.getResultFail("角色不存在，无法进行删除操作");
        }
        int countCopy = roleCopyMapper.countRoleCopyByRoleId(roleDeleteBO.getRoleId());
        if (countCopy > 0) {
            return GetResult.getResultFail(role.getRoleName() + "存在审核记录，无法删除");
        }
        int count = operatorMapper.countOperatorByRoleId(roleDeleteBO.getRoleId());
        if (count > 0) {
            return GetResult.getResultFail(role.getRoleName() + "已绑定用户，无法删除");
        }
        Integer taskRoleId = taskScenarioMapper.selectCountBYRoleId(roleDeleteBO.getRoleId());
        if (taskRoleId > 0) {
            return GetResult.getResultFail(role.getRoleName() + "已经绑定任务场景，无法删除");
        }
        //定义日志信息
        String logName = "删除角色";
        String operationDesc = "操作人" + opName + "删除了角色" + role.getRoleName();

        //将删除信息添加到临时表
        RoleCopy roleCopy = new RoleCopy();
        DtoUtils.cloneBeanToBean(roleCopy, role);
        roleCopy.setAuditId(PrimaryKeyUtil.getPrimaryKey());
        roleCopy.setAuditType(StatusConstant.AUDIT_TYPE_DELETE);
        roleCopy.setCreateOp(opId);
        roleCopy.setAuditSn(roleCopyMapper.maxAuditSn(role.getRoleId()) + 1);
        roleCopy.setAuditor(roleDeleteBO.getAuditor());
        roleCopy.setEntityRecord(JSON.toJSONString(role));
        if ("1".equals(roleDeleteBO.getAuditType())) {
            roleCopy.setAuditFlag(StatusConstant.AUDIT_FLAG_PASS);
            //修改角色主表信息
            Role deleteRole = new Role();
            DtoUtils.cloneBeanToBean(deleteRole, roleCopy);
            redisUtils.clearPopedomListByRoleId(deleteRole.getRoleId());
            int result = roleMapper.deleteRole(deleteRole);
            //删除角色权限表原有的权限
            popedomMapper.deleteRolePopedom(deleteRole.getRoleId());
            roleCopyMapper.insert(roleCopy);
            if (result > 0) {
                //详细日志添加
                operatorLogService.insert(operationDesc, logName, "1", opId, opName, orgId);
                return GetResult.getResultSuccess("删除角色成功！");
            }
            return GetResult.getResultErr("删除失败！");
        }
        roleCopy.setAuditFlag(StatusConstant.AUDIT_FLAG_DEFAULT);
        int result = roleCopyMapper.insert(roleCopy);
        //返回处理结果
        if (result > 0) {
            log.info("删除角色信息：删除成功，待审核。审核编号: {}", roleCopy.getAuditId());
            //详细日志添加
            operatorLogService.insert(operationDesc, logName, "1", opId, opName, orgId);
            return GetResult.getResultSuccess("删除角色成功，待审核！");
        }
        log.info("删除角色信息：删除失败");
        return GetResult.getResultFail("删除失败");
    }

    @Override
    public BaseResult batchDeleteRole(HttpServletRequest request, RoleDeleteBO deleteBO) throws Exception {
        String[] roleIds = deleteBO.getRoleId().split(",");
        for (String roleId : roleIds) {
            RoleDeleteBO roleDeleteBO = new RoleDeleteBO();
            BeanUtil.copyProperties(deleteBO, roleDeleteBO);
            roleDeleteBO.setRoleId(roleId);
            BaseResult result = deleteRole(request, roleDeleteBO);
            if (!"00".equals(result.getDataCode())) {
                return GetResult.getResultFail(result.getDataMessage());
            }
        }
        String message = "1".equals(deleteBO.getAuditType()) ? "删除角色成功！" : "删除角色成功，待审核！";
        return GetResult.getResultSuccess(message);
    }

    /**
     * @Description: 获取角色下拉框
     * @Author: jiy.fang
     * @Date: 2019/8/2 15:05
     */
    @Override
    public List<Role> getRoleLists(HttpServletRequest request) throws Exception {
        return roleMapper.getRoles();
    }

    @Override
    public List<RoleDTO> getListRoleExport(HttpServletRequest request, RoleQueryBO roleQueryBO) {
        String orgId = TokenUtil.getOrgId(request.getHeader("token"));
        if (null == roleQueryBO.getOrgId() || "".equals(roleQueryBO.getOrgId())) {
            roleQueryBO.setOrgId(orgId);
        }
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("orgId", roleQueryBO.getOrgId());
        queryMap.put("roleName", roleQueryBO.getRoleName());
        queryMap.put("operatorRole", operatorRole);
        return roleMapper.getRoleListByPage(queryMap);
    }

    private void addRolePopedom(Role role, RoleCopy roleCopy) {
        //获取最新分配的权限
        List<RolePopedom> newRolePopedomList = popedomMapper.findTepRolePopedomListByRoleId(role.getRoleId(),
                roleCopy.getAuditId());
        //更新角色权限表
        if (!newRolePopedomList.isEmpty()) {
            popedomMapper.insertRolePopedom(newRolePopedomList);
        }
        log.info("角色权限分配通过审核，审核编号={}，机构编号={}", roleCopy.getAuditId(), roleCopy.getOrgId());
        //获取该角色下所属权限,并被迫登出
        List<Operator> operatorList = operatorMapper.getListOperatorByroleId(roleCopy.getRoleId());
        for (Operator operator1 : operatorList) {
            disableLogout(operator1);
        }
    }

    /**
     * 角色权限修改--审核通过后，下属用户被迫登出
     */
    private void disableLogout(Operator operator) {
        RedisUtil.del("login:operator:" + operator.getOpName());
        RedisUtil.del("popedom:loginOperator:" + operator.getRoleId());
        log.info("用户被停用，已登出");
    }
}
